package com.hk.pinda.zuul.filter;

import cn.hutool.core.util.StrUtil;
import com.hk.common.adapter.IgnoreTokenConfig;
import com.hk.pinda.base.BaseResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import java.nio.charset.StandardCharsets;

/**
 * 基础 网关过滤器
 *
 *   GlobalFilter 全局过滤器，它会在 请求进入网关之后，在路由之前执行。
 *  通常用于全局性的逻辑，比如 日志记录，全局异常处理d等。
 *  在网关鉴权中，可以利用全局过滤器 进行统一的身份验证和权限检查
 */
@Slf4j
public abstract class BaseFilter implements GlobalFilter, Ordered {


    @Value("${server.servlet.context-path}")
    protected String zuulPrefix;

    /**
     * 判断当前请求uri是否需要忽略
     */
    protected boolean isIgnoreToken(ServerWebExchange exchange) {
        ServerHttpRequest request = exchange.getRequest();
        // HttpServletRequest request = RequestContext.getCurrentContext().getRequest();
        // String uri = request.getRequestURI();
        // 获取请求的 URI
        String uri = request.getURI().getPath().toString();
        log.info("======= 请求的url地址为：" + uri);
        uri = StrUtil.subSuf(uri, zuulPrefix.length());
        uri = StrUtil.subSuf(uri, uri.indexOf("/", 1));
        boolean ignoreToken = IgnoreTokenConfig.isIgnoreToken(uri);
        return ignoreToken;
    }

    /**
     * 网关抛异常
     *
     * @param errMsg
     * @param errCode
     * @param httpStatusCode
     */
    protected void errorResponse(ServerHttpResponse response , String errMsg, int errCode, int httpStatusCode) {
       BaseResult tokenError = BaseResult.fail(errCode, errMsg);
        byte[] bytes = tokenError.toString().getBytes(StandardCharsets.UTF_8);
        // 返回错误码
        response.setStatusCode(HttpStatus.UNAUTHORIZED); // 标记为不能访问的状态码 401
        // 返回错误内容
        DataBuffer dataBuffer = response.bufferFactory().wrap(bytes);
        response.writeWith(Flux.just(dataBuffer));
        // 过滤该请求，不对其进行路由
        // response.setComplete();
    }
}
